home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / USBKeypad / USBKeypad.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  12.5 KB  |  366 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        USBKeypad.c
  3.  
  4.     Contains:    xxx put contents here xxx
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "USBKeypad.h"
  19.  
  20. usbKeyPadPBStruct myParamBlock;
  21. usbKeyPadPBStruct shimParamBlock;
  22.  
  23.  
  24. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock);
  25.  
  26. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  27. {
  28.     paramblock->usbReference = theDeviceRef;
  29.     paramblock->pbVersion = kUSBCurrentPBVersion;
  30.     paramblock->usb.cntl.WIndex = 0;             
  31.     paramblock->usbBuffer = nil;        
  32.     paramblock->usbStatus = noErr;
  33.     paramblock->usbReqCount = 0;
  34.     paramblock->usb.cntl.WValue = 0;
  35.     paramblock->usbFlags = 0;
  36.     paramblock->usbOther = 0;
  37. }
  38.  
  39. static Boolean immediateError(OSStatus err)
  40. {
  41.     return((err != kUSBPending) && (err != noErr) );
  42. }
  43.  
  44. void InitiateTransaction(USBPB *pb)
  45. {
  46. register usbKeyPadPBStruct *pKeyPadPB;
  47. OSStatus myErr;
  48.  
  49.     pKeyPadPB = (usbKeyPadPBStruct *)(pb);
  50.     pKeyPadPB->transDepth++;
  51.     if (pKeyPadPB->transDepth < 0)
  52.     {
  53.         USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: transDepth < 0 (initiation)", pKeyPadPB->pb.usbRefcon );
  54.     }
  55.     
  56.     if (pKeyPadPB->transDepth > 1)
  57.     {
  58.         USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: transDepth > 1 (initiation)", pKeyPadPB->pb.usbRefcon );
  59.     }
  60.     
  61.     switch(pKeyPadPB->pb.usbRefcon & ~kRetryTransaction)
  62.     {
  63.         case kFindInterface:
  64.             InitParamBlock(pKeyPadPB->deviceRef, &pKeyPadPB->pb);
  65.             pKeyPadPB->pb.usb.cntl.WIndex = 0;
  66.             pKeyPadPB->pb.usb.cntl.WValue = 0;
  67.             pKeyPadPB->pb.usbClassType = kUSBHIDInterfaceClass;
  68.             pKeyPadPB->pb.usbSubclass = 0;
  69.             pKeyPadPB->pb.usbProtocol = kUSBKeyboardInterfaceProtocol;
  70.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  71.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  72.             myErr = USBFindNextInterface(pb);
  73.             if(immediateError(myErr))
  74.             {
  75.                 USBExpertFatalError(pKeyPadPB->pb.usbReference, kUSBInternalErr, "\pTenKey Driver: USBFindNextInterface (immediate error)", myErr);
  76.                 pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  77.             }
  78.             break;
  79.             
  80.         case kConfigureDevice:
  81.             InitParamBlock(pKeyPadPB->deviceRef, &pKeyPadPB->pb);
  82.             pKeyPadPB->pb.usb.cntl.WValue = pKeyPadPB->configurationNumber;
  83.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  84.             
  85.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  86.             myErr = USBOpenDevice(pb);
  87.             if(immediateError(myErr))
  88.             {
  89.                 USBExpertFatalError(pKeyPadPB->pb.usbReference, kUSBInternalErr, "\pTenKey Driver: USBOpenDevice (immediate error)", myErr);
  90.                 pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  91.             }
  92.             break;
  93.             
  94.         case kNewInterfaceRef:
  95.             InitParamBlock(pKeyPadPB->deviceRef, &pKeyPadPB->pb);
  96.             pKeyPadPB->pb.usb.cntl.WIndex = pKeyPadPB->interfaceNumber;
  97.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  98.             
  99.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  100.             myErr = USBNewInterfaceRef(pb);
  101.             if(immediateError(myErr))
  102.             {
  103.                 USBExpertFatalError(pKeyPadPB->pb.usbReference, kUSBInternalErr, "\pTenKey Driver: USBNewInterfaceRef (immediate error)", myErr);
  104.                 pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  105.             }
  106.             break;
  107.             
  108.         case kConfigureInterface:
  109.             InitParamBlock(pKeyPadPB->interfaceRef, &pKeyPadPB->pb);
  110.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  111.             
  112.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  113.             myErr = USBConfigureInterface(pb);
  114.             if(immediateError(myErr))
  115.             {
  116.                 USBExpertFatalError(pKeyPadPB->pb.usbReference, kUSBInternalErr, "\pTenKey Driver: USBConfigureInterface (immediate error)", myErr);
  117.                 pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  118.             }
  119.             break;
  120.             
  121.         case kGetReportDescriptor:
  122.             InitParamBlock(pKeyPadPB->deviceRef, &pKeyPadPB->pb);
  123.             pKeyPadPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBIn, kUSBStandard, kUSBInterface);
  124.             pKeyPadPB->pb.usb.cntl.BRequest = kUSBRqGetDescriptor;
  125.             pKeyPadPB->pb.usb.cntl.WValue = (0x22 << 8) + 1;             // get the first report descriptor
  126.             pKeyPadPB->pb.usb.cntl.WIndex = pKeyPadPB->interfaceNumber;
  127.             pKeyPadPB->pb.usbReqCount = 0x66;
  128.             pKeyPadPB->pb.usbBuffer = pKeyPadPB->hidReportDescriptor;
  129.             
  130.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  131.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  132.             myErr = USBDeviceRequest(pb);
  133.             if(immediateError(myErr))
  134.             {
  135.                 USBExpertFatalError(pKeyPadPB->pb.usbReference, kUSBInternalErr, "\pTenKey Driver: kGetReportDescriptor - immediate error", myErr);
  136.             }
  137.             break;
  138.         
  139.         case kFindInterruptPipe:
  140.             USBExpertStatus(pKeyPadPB->interfaceRef, "\pTenKey Driver: kFindInterruptPipe - interfaceRef", pKeyPadPB->interfaceRef);
  141.             InitParamBlock(pKeyPadPB->interfaceRef, &pKeyPadPB->pb);
  142.             pKeyPadPB->pb.usbFlags = kUSBIn;
  143.             pKeyPadPB->pb.usbClassType = kUSBInterrupt; 
  144.             
  145.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  146.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  147.             myErr = USBFindNextPipe(&pKeyPadPB->pb);
  148.             if (immediateError(myErr))
  149.             {
  150.                 USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: kFindInterruptPipe (immediate error)", myErr);
  151.                 pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  152.             }
  153.             break;
  154.             
  155.         case kReadInterruptPipe:
  156.             InitParamBlock(pKeyPadPB->pipeRef, &pKeyPadPB->pb);
  157.  
  158.             pKeyPadPB->pb.usbBuffer = (Ptr)pKeyPadPB->hidReport;
  159.             pKeyPadPB->pb.usbReqCount = 4;
  160.             pKeyPadPB->pb.usb.cntl.WIndex = pKeyPadPB->interfaceNumber;    
  161.             
  162.             pKeyPadPB->pb.usbRefcon |= kCompletionPending;
  163.             pKeyPadPB->pb.usbCompletion = (USBCompletion)TransactionCompletionProc;
  164.             myErr = USBIntRead(&pKeyPadPB->pb);
  165.             if(immediateError(myErr))
  166.             {
  167.                 USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: kReadInterruptPipe (ImmediateError)", myErr);
  168.             }
  169.             break;
  170.             
  171.             
  172.         default:
  173.             USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: Transaction completed with bad refcon value", pKeyPadPB->pb.usbRefcon );
  174.             pKeyPadPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  175.             break;
  176.     }
  177.     
  178. // At this point the control is returned to the system.  If a USB transaction
  179. // has been initiated, then it will call the Complete procs
  180. // (below) to handle the results of the transaction.
  181. }
  182.  
  183. void TransactionCompletionProc(USBPB *pb)
  184. {
  185. unsigned char    * errstring;
  186. register usbKeyPadPBStruct *pKeyPadPB;
  187. USBPipeState pipeState;
  188.  
  189.     pKeyPadPB = (usbKeyPadPBStruct *)(pb);
  190.     pKeyPadPB->transDepth--;
  191.     if (pKeyPadPB->transDepth < 0)
  192.     {
  193.         USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: transDepth < 0 (completion)", pKeyPadPB->pb.usbRefcon );
  194.     }
  195.     
  196.     if (pKeyPadPB->transDepth > 1)
  197.     {
  198.         USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: transDepth > 1 (completion)", pKeyPadPB->pb.usbRefcon );
  199.     }
  200.     
  201.     if(pKeyPadPB->pb.usbStatus != noErr)                                                    // was there an error?
  202.     {
  203.         switch(pKeyPadPB->pb.usbRefcon & 0x0fff)                                            // yes, so show where the error occurred
  204.         {
  205.             case kFindInterface:                  errstring = "\pTenKey Driver: Error during kFindInterface"; break;
  206.             case kConfigureDevice:                errstring = "\pTenKey Driver: Error during kConfigureDevice"; break;
  207.             case kNewInterfaceRef:                errstring = "\pTenKey Driver: Error during kNewInterfaceRef"; break;
  208.             case kConfigureInterface:              errstring = "\pTenKey Driver: Error during kConfigureInterface"; break;
  209.             case kGetReportDescriptor:              errstring = "\pTenKey Driver: Error during kGetReportDescriptor"; break;
  210.             case kFindInterruptPipe:              errstring = "\pTenKey Driver: Error during kFindInterruptPipe"; break;
  211.             case kReadInterruptPipe:              errstring = "\pTenKey Driver: Error during kReadInterruptPipe"; break;
  212.         };
  213.         USBExpertFatalError(pKeyPadPB->deviceRef, pKeyPadPB->pb.usbStatus, errstring, (pKeyPadPB->pb.usbRefcon & 0x0fff));
  214.         
  215.         pKeyPadPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  216.         pKeyPadPB->pb.usbRefcon |= kRetryTransaction;
  217.         pKeyPadPB->retryCount--;
  218.         
  219.         if ((!pKeyPadPB->retryCount)    || (pKeyPadPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  220.         {                                                                                    // or received an abort?
  221.             USBExpertStatus(pKeyPadPB->deviceRef, "\pTenKey Driver: Pipe abort or unable to recover from error", pKeyPadPB->deviceRef);
  222.             pKeyPadPB->pb.usbRefcon = kReturnFromDriver;                                    // if so, just exit.
  223.         }
  224.         else                                                                                // if it didn't abort and there's retries left, then...
  225.         {
  226.             if (pKeyPadPB->pipeRef)                                                        // check if the pipe is open.
  227.             {
  228.                 USBGetPipeStatusByReference(pKeyPadPB->pipeRef, &pipeState);                // yes, so what it's state?
  229.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  230.                 {
  231.                     USBExpertStatus(pKeyPadPB->deviceRef, "\pTenKey Driver: Pipe is open and stalled, clearing stall...", pKeyPadPB->deviceRef);
  232.                     USBClearPipeStallByReference(pKeyPadPB->pipeRef);
  233.                 }
  234.             }
  235.         }
  236.     }
  237.     else
  238.     {
  239.         pKeyPadPB->pb.usbRefcon &= ~kRetryTransaction;
  240.         pKeyPadPB->retryCount = kKeyboardRetryCount;
  241.     }
  242.  
  243.     if (pKeyPadPB->pb.usbRefcon & kCompletionPending)             
  244.     {                                                
  245.         pKeyPadPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  246.         switch(pKeyPadPB->pb.usbRefcon)
  247.         {
  248.             case kFindInterface:
  249.                 if ((pKeyPadPB->pb.usbClassType == kUSBHIDInterfaceClass) && 
  250.                     (pKeyPadPB->pb.usbProtocol == kUSBKeyboardInterfaceProtocol))
  251.                 {
  252.                     pKeyPadPB->pb.usbRefcon = kConfigureDevice;
  253.                     pKeyPadPB->interfaceNumber = pKeyPadPB->pb.usb.cntl.WIndex;
  254.                     pKeyPadPB->configurationNumber = pKeyPadPB->pb.usb.cntl.WValue;
  255.                     pKeyPadPB->interfaceSubClass = pKeyPadPB->pb.usbSubclass;
  256.                 }
  257.                 else
  258.                 {
  259.                     USBExpertStatus(pKeyPadPB->deviceRef, "\pTenKey Driver: Keyboard interface was not found", pKeyPadPB->deviceRef);
  260.                     pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  261.                 }
  262.                 break;
  263.                 
  264.             case kConfigureDevice:
  265.                 pKeyPadPB->pb.usbRefcon = kNewInterfaceRef;
  266.                 break;
  267.                 
  268.             case kNewInterfaceRef:
  269.                 pKeyPadPB->interfaceRef = pKeyPadPB->pb.usbReference;
  270.                 pKeyPadPB->pb.usbRefcon = kConfigureInterface;
  271.                 break;
  272.             
  273.             case kConfigureInterface:
  274.                 pKeyPadPB->pb.usbRefcon = kFindInterruptPipe;
  275.                 break;
  276.             
  277.             case kGetReportDescriptor:
  278.                 pKeyPadPB->pb.usbRefcon = kFindInterruptPipe;
  279.                 break;
  280.                 
  281.             case kFindInterruptPipe:
  282.                 if ((pKeyPadPB->pb.usbClassType == kUSBInterrupt) && 
  283.                     (pKeyPadPB->pb.usbFlags == kUSBIn))
  284.                 {
  285.                     pKeyPadPB->hidReportSize = pKeyPadPB->pb.usb.cntl.WValue;
  286.                     pKeyPadPB->pipeRef = pKeyPadPB->pb.usbReference;
  287.                     pKeyPadPB->pb.usbRefcon = kReadInterruptPipe;
  288.                 }
  289.                 else
  290.                 {
  291.                     pKeyPadPB->pb.usbRefcon = kReturnFromDriver;
  292.                 }
  293.                 break;
  294.                 
  295.             case kReadInterruptPipe:
  296.                 //DebugStr("\pKeypad read completed");
  297.                 ProcessInterruptReport(pKeyPadPB->hidReport);
  298.                 pKeyPadPB->pb.usbRefcon = kReadInterruptPipe;
  299.                 break;
  300.                 
  301.             default:
  302.                 USBExpertFatalError(pKeyPadPB->deviceRef, kUSBInternalErr, "\pTenKey Driver: Transaction completed with bad refcon value", pKeyPadPB->pb.usbRefcon );
  303.                 pKeyPadPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  304.                 break;
  305.         }
  306.     }
  307.     if (!(pKeyPadPB->pb.usbRefcon & kReturnFromDriver))
  308.         InitiateTransaction(pb);
  309. }
  310.  
  311.  
  312. void DriverEntry(USBDeviceRef device, USBDeviceDescriptorPtr pDesc, UInt32 busPowerAvailable)
  313. {
  314. #pragma unused (busPowerAvailable)
  315.  
  316. static Boolean beenThereDoneThat = false;
  317.  
  318.     if(beenThereDoneThat)
  319.     {
  320.         USBExpertFatalError(device, kUSBInternalErr, "\pTenKey is not reentrant", 12);
  321.         return;
  322.     }
  323.     beenThereDoneThat = true;
  324.     
  325. //    DebugStr("\pIn Key Pad Interface entry routine");
  326.     shimParamBlock.deviceDescriptor = *pDesc;                
  327.     shimParamBlock.transDepth = 0;                            
  328.     shimParamBlock.retryCount = kKeyboardRetryCount;
  329.     shimParamBlock.deviceRef = device;
  330.     shimParamBlock.interfaceRef = 0;
  331.     shimParamBlock.pipeRef = 0;
  332.     
  333.     shimParamBlock.deviceRef = device;        
  334.     shimParamBlock.interfaceRef = nil;        
  335.     shimParamBlock.pipeRef = nil;        
  336.     
  337.     InitParamBlock(device, &shimParamBlock.pb);
  338.     shimParamBlock.pb.pbLength = sizeof(usbKeyPadPBStruct);
  339.     shimParamBlock.pb.usbRefcon = 0;                
  340.  
  341.     myParamBlock.deviceDescriptor = *pDesc;                
  342.     myParamBlock.transDepth = 0;                            
  343.     myParamBlock.retryCount = kKeyboardRetryCount;
  344.     myParamBlock.deviceRef = device;
  345.     myParamBlock.interfaceRef = 0;
  346.     myParamBlock.pipeRef = 0;
  347.  
  348.     myParamBlock.deviceRef = device;        
  349.     myParamBlock.interfaceRef = nil;        
  350.     myParamBlock.pipeRef = nil;    
  351.     
  352.     myParamBlock.sendRawReportFlag = false;
  353.     myParamBlock.hidEmulationInit = false;
  354.     
  355.     InitParamBlock(device, &myParamBlock.pb);
  356.     myParamBlock.pb.pbLength = sizeof(usbKeyPadPBStruct);
  357.     myParamBlock.pb.usbRefcon = kFindInterface;        /* Start with setting the interface protocol */
  358.     
  359.     
  360.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  361.     InitiateTransaction(&myParamBlock.pb);
  362. }
  363.  
  364.  
  365.  
  366.